package com.fl.nettydemo.c4;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

@Slf4j
public class Server {
    public static void main(String[] args) {
        try {
            //使用nio 阻塞模式 单线程
            //开启selector选择器
            Selector selector = Selector.open();
            //开启socket
            ServerSocketChannel socket = ServerSocketChannel.open();
            //将服务器设置为非阻塞模式
            socket.configureBlocking(false);
            SelectionKey ssckey = socket.register(selector, 0, null);
            ssckey.interestOps(SelectionKey.OP_ACCEPT);
            //指定服务端端口
            socket.bind(new InetSocketAddress(9999));
            while (true) {
                //没有事件就线程阻塞，有事件恢复运行
                selector.select();
                //selectedKeys集合内部 有多少事件就生成多少线程
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    //每次循环处理要自己删除事件key
                    iterator.remove();
                    log.info("key：{}", key);
                    if (key.isAcceptable()) {
                        ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                        SocketChannel sc = channel.accept();
                        sc.configureBlocking(false);
                        // 将buffer 作为附件关联到选择器
                        ByteBuffer buffer = ByteBuffer.allocate(16);
                        //将通道注册到选择器
                        SelectionKey selectionKey = sc.register(selector, 0, buffer);
                        //关注读事件
                        selectionKey.interestOps(SelectionKey.OP_READ);
                        log.info("{}", sc);
                    } else if (key.isReadable()) {
                        try {
                            SocketChannel channel = (SocketChannel) key.channel();
                            ByteBuffer buffer = (ByteBuffer) key.attachment();
                            //客户端断开返回-1
                            int read = channel.read(buffer);
                            if (read == -1) {
                                key.cancel();
                            }else {
                                if (buffer.position() == buffer.limit()) {
                                    ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity()*2);
                                    buffer.flip();
                                    newBuffer.put(buffer);
                                    key.attach(newBuffer);
                                }else {
                                    buffer.flip();
                                    log.info("读数据：{}", StandardCharsets.UTF_8.decode(buffer));
                                    buffer.clear();
                                }
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                            //发生异常时，将选择器内当前事件移除
                            key.cancel();
                        }
                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
